//
//  HttpConnector.m
//  libHttpConnector
//
//  Created by wuyoujian on 06/26/12.
//  Copyright (c) 2012 asiainfo-linkage. All rights reserved.
//

#include <sys/timeb.h>
#import "HttpConnector.h"
#import "ASIHTTPRequest.h"
#import "ASIDataCompressor.h"
#import "ASIDataDecompressor.h"
#import "ASIFormDataRequest.h"
#import "ASIHTTPRequestDelegate.h"
#import "GTMBase64.h"

static HttpConnector* httpConnector = nil;

@interface HttpConnector() <ASIHTTPRequestDelegate>
- (void)requestFinished_static:(HttpConnector*)request msg:(id <MessageDelegate>)message;

@end


@implementation HttpConnector

@synthesize serviceUrl;
@synthesize timeout;
@synthesize statusDelegate;
@synthesize receiveString;
@synthesize receiveData;
@synthesize httpRequest;
@synthesize allowCompressed;
@synthesize isPostXML;

+ (id)sharedHttpConnector {
	@synchronized ([HttpConnector class]) {
		if (nil == httpConnector) {
			httpConnector = [[HttpConnector alloc] init];
		}
	}
	
	return httpConnector;
}

- (id)init {
	if (self = [super init]) {
		serviceUrl = nil;
		timeout = 20;
		statusDelegate = nil;
        allowCompressed = NO;
	}
	
	return self;
}

- (void)dealloc{
    [serviceUrl release];
    [receiveData release];
    [receiveString release];
    [httpRequest clearDelegatesAndCancel];
    [httpRequest release];
    [super dealloc];
}

-(void)cancelRequest{
    [httpRequest cancel];
    [httpRequest clearDelegatesAndCancel];
}

- (void)sendMessage_static:(id <MessageDelegate>)message xmlFile:(NSString*)file{
    if (nil != message && nil != [message getRequest]){
        HttpConnector* httpServer = [[HttpConnector alloc] init];
        NSString *strXml = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
        NSData   *xmlData = [strXml dataUsingEncoding:NSUTF8StringEncoding];
        httpServer.receiveString = strXml;
        httpServer.receiveData = xmlData;
        [self requestFinished_static:httpServer msg:message];
        [httpServer release];        
    }
}

- (void)requestFinished_static:(HttpConnector*)request msg:(id <MessageDelegate>)message{
    NSString* xmlStr = request.receiveString;
    if (nil != message) {
        [message parseResponse:xmlStr];
    }
    
    if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestDidFinished:)]) {
        [statusDelegate performSelectorOnMainThread:@selector(requestDidFinished:)
                                         withObject:message
                                      waitUntilDone:[NSThread isMainThread]];
    }
}

- (void)uploadPhotoMessage:(id <MessageDelegate>)message synchronously:(BOOL)isSynchronous SessionId:(NSString *)SessionStr PostKey:(NSString*)postKey{
	NSString* requestMessage = nil;
	if (nil != message && nil != (requestMessage = [message getRequest])) {
		NSURL* requestUrl = [NSURL URLWithString:serviceUrl];
        ASIFormDataRequest* request = [[ASIFormDataRequest alloc] initWithURL:requestUrl];
        //[ASIFormDataRequest requestWithURL:requestUrl];
		self.httpRequest = request;
        [request release];
        
        NSInteger systemVersion = 0;
        NSString* versionStr = [[UIDevice currentDevice] systemVersion];
        if (nil != versionStr && [versionStr length] > 0) {
            systemVersion = [[versionStr substringToIndex:1] intValue];
        }else{
            systemVersion = 4;
        }
        
        if (systemVersion >= 4) {
            [httpRequest setShouldContinueWhenAppEntersBackground:YES];
        }
        
        //[httpRequest setShouldAttemptPersistentConnection:NO];
        [httpRequest setNumberOfTimesToRetryOnTimeout:0];
		[httpRequest addRequestHeader:@"Content-Type" value:@"application/x-www-form-urlencoded"];
        [httpRequest addRequestHeader:@"cookie" value:[NSString stringWithFormat:@"%@",SessionStr]];
		[httpRequest setTimeOutSeconds:timeout];
		[httpRequest setDelegate:self];
        [httpRequest setRequestMethod:@"POST"];
		[httpRequest setDownloadProgressDelegate:self];
        [httpRequest setUserInfo:[NSDictionary dictionaryWithObject:message forKey:@"MESSAGE_OBJECT"]];
        
//        NSData* requestData = [requestMessage dataUsingEncoding:NSUTF8StringEncoding];
//        //压缩
//        NSData* compressData = [ASIDataCompressor compressData:requestData error:nil];
//        NSString* base64Str = [[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding];
        [httpRequest setPostValue:requestMessage forKey:postKey];//imgBase64
        NSLog(@"postKey=%@",requestMessage);
        
		if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestWillBeSent)]) {
			[statusDelegate performSelectorOnMainThread:@selector(requestWillBeSent)
											 withObject:nil
										  waitUntilDone:[NSThread isMainThread]];
		}
		
		if (YES == isSynchronous) {
			[httpRequest startSynchronous];
		}else {
			[httpRequest startAsynchronous];
		}
	}
}

- (void)sendMessage:(id <MessageDelegate>)message synchronously:(BOOL)isSynchronous SessionId:(NSString *)SessionStr{
	NSString* requestMessage = nil;
	if (nil != message && nil != (requestMessage = [message getRequest])) {
		NSURL* requestUrl = [NSURL URLWithString:serviceUrl];
        ASIFormDataRequest* request = [[ASIFormDataRequest alloc] initWithURL:requestUrl];
        //[ASIFormDataRequest requestWithURL:requestUrl];
		self.httpRequest = request;
        [request release];
        
        NSInteger systemVersion = 0;
        NSString* versionStr = [[UIDevice currentDevice] systemVersion];
        if (nil != versionStr && [versionStr length] > 0) {
            systemVersion = [[versionStr substringToIndex:1] intValue];
        }else{
            systemVersion = 4;
        }
        
        if (systemVersion >= 4) {
            [httpRequest setShouldContinueWhenAppEntersBackground:YES];
        }
        
        //[httpRequest setShouldAttemptPersistentConnection:NO];
        [httpRequest setNumberOfTimesToRetryOnTimeout:0];
		[httpRequest addRequestHeader:@"Content-Type" value:@"application/x-www-form-urlencoded"];
        [httpRequest addRequestHeader:@"cookie" value:[NSString stringWithFormat:@"%@",SessionStr]];
		[httpRequest setTimeOutSeconds:timeout];
		[httpRequest setDelegate:self];
        [httpRequest setRequestMethod:@"POST"];
		[httpRequest setDownloadProgressDelegate:self];
        [httpRequest setUserInfo:[NSDictionary dictionaryWithObject:message forKey:@"MESSAGE_OBJECT"]];
        NSLog(@"原始数据 %@",requestMessage);
        if (self.allowCompressed) {
            [httpRequest setAllowCompressedResponse:YES];

            NSData* requestData = [requestMessage dataUsingEncoding:NSUTF8StringEncoding];
            //压缩
            NSData* compressData = [ASIDataCompressor compressData:requestData error:nil];
            NSString* base64Str = [GTMBase64 stringByEncodingData:compressData];
            if (isPostXML) {
                [httpRequest setPostValue:base64Str forKey:@"xmlmsg"];
            }else{
                [httpRequest setPostValue:base64Str forKey:@"msg"];
            }
            NSLog(@"base64Str=%@",base64Str);
        }else{
            [httpRequest setAllowCompressedResponse:NO];
            if (isPostXML) {
                [httpRequest setPostValue:requestMessage forKey:@"xmlmsg"];
            }else{
                [httpRequest setPostValue:requestMessage forKey:@"msg"];
            }
        }
        
		if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestWillBeSent)]) {
			[statusDelegate performSelectorOnMainThread:@selector(requestWillBeSent)
											 withObject:nil
										  waitUntilDone:[NSThread isMainThread]];
		}
		
		if (YES == isSynchronous) {
			[httpRequest startSynchronous];
		}else {
			[httpRequest startAsynchronous];
		}
	}
}

- (void)requestStarted:(ASIHTTPRequest*)request {
	if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestDidSend)]) {
		[statusDelegate performSelectorOnMainThread:@selector(requestDidSend) withObject:nil waitUntilDone:[NSThread isMainThread]];
	}
}

- (void)requestFinished:(ASIHTTPRequest*)request {
	int responseCode = request.responseStatusCode;
	if (200 == responseCode) {
        NSString* responseMessage = nil;
        if (self.allowCompressed) {
//            NSLog(@"request.rawResponseData:%@",request.rawResponseData);
//            NSLog(@"request.responseData:%@",request.responseData);
//            NSLog(@"request.rawResponseData string:%@",[[[NSString alloc] initWithData:request.responseData encoding:NSUTF8StringEncoding] autorelease]);
            NSData* base64Data = [GTMBase64 decodeData:request.responseData];
            NSString* sourceStr = [[NSString alloc] initWithData:base64Data encoding:NSUTF8StringEncoding];
//            NSLog(@"source data:%@",sourceStr);
            [sourceStr release];
            //解压gzip
            NSData *decompressData = [ASIDataDecompressor uncompressData:base64Data error:nil];
            NSString* decompressStr = [[NSString alloc] initWithData:decompressData encoding:NSUTF8StringEncoding];
            responseMessage = [NSString stringWithString:decompressStr];
            [decompressStr release];
        }else{
            responseMessage = request.responseString;
        }
    
		id <MessageDelegate> message = [request.userInfo objectForKey:@"MESSAGE_OBJECT"];
		if (nil != message) {
			[message parseResponse:responseMessage];
		}
		
		if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestDidFinished:)]) {
			[statusDelegate performSelectorOnMainThread:@selector(requestDidFinished:)
											 withObject:message
										  waitUntilDone:[NSThread isMainThread]];
		}
	} else {
		if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestFailed:)]) {
			id <MessageDelegate> message = [request.userInfo objectForKey:@"MESSAGE_OBJECT"];
			
			NSMutableDictionary* errorInfo = [[NSMutableDictionary alloc] initWithCapacity:0];
			[errorInfo setObject:message forKey:@"MESSAGE_OBJECT"];
			[errorInfo setObject:@"8888" forKey:@"STATUS_CODE"];
			
			[statusDelegate performSelectorOnMainThread:@selector(requestFailed:)
											 withObject:errorInfo
										  waitUntilDone:[NSThread isMainThread]];
			
			[errorInfo release];
		}
	}
}

- (void)requestFailed:(ASIHTTPRequest*)request {
	if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestFailed:)]) {
		id <MessageDelegate> message = [request.userInfo objectForKey:@"MESSAGE_OBJECT"];
		int statusCode = [request.error code];
		
		NSString* errorCode = @"9999";
		if (ASIConnectionFailureErrorType == statusCode) {
			errorCode = @"8888";
		} else if (ASIRequestTimedOutErrorType == statusCode) {
			errorCode = @"5555";
		}
		
		NSMutableDictionary* errorInfo = [[NSMutableDictionary alloc] initWithCapacity:0];
		[errorInfo setObject:message forKey:@"MESSAGE_OBJECT"];
		[errorInfo setObject:errorCode forKey:@"STATUS_CODE"];
		
		[statusDelegate performSelectorOnMainThread:@selector(requestFailed:)
										 withObject:errorInfo
									  waitUntilDone:[NSThread isMainThread]];
		
		[errorInfo release];
	}
}

- (void)request:(ASIHTTPRequest*)request didReceiveBytes:(long long)bytes {
	if (nil != statusDelegate && YES == [statusDelegate respondsToSelector:@selector(requestStatus:)]) {
		if (0 < [request contentLength] + [request partialDownloadSize]) {
			
			float percentage =
			([request totalBytesRead] * 1.0) / (([request contentLength] + [request partialDownloadSize]) * 1.0);
			
			double currentTime = CFAbsoluteTimeGetCurrent();
			double timePeriod = currentTime - lastActionTime;
			double speed = bytes * 1.0 / (1024 * timePeriod);
			lastActionTime = CFAbsoluteTimeGetCurrent();
			
			NSMutableDictionary* statusInfo = [[NSMutableDictionary alloc] initWithCapacity:0];
			[statusInfo setObject:[NSNumber numberWithFloat:percentage] forKey:@"PERCENTAGE"];
			[statusInfo setObject:[NSNumber numberWithFloat:speed] forKey:@"SPEED"];
			
			[statusDelegate performSelectorOnMainThread:@selector(requestStatus:)
											 withObject:statusInfo
										  waitUntilDone:[NSThread isMainThread]];
			
			[statusInfo release];
		}
	}
}

@end
